/*
 * @Author: hanyuanjiao
 * @Date: 2025-07-21 06:52:28
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2025-08-18 21:29:36
 * @Description: 请填写简介
 */

#ifndef INSTR_H
#define INSTR_H
#include <stdint.h>

struct _instr_info_t;
typedef struct _instr_t
{
    //操作码
    uint8_t opcode;
    //操作数1
    uint8_t op0;
    //操作数2
    uint8_t op1;
    //指令描述的方向索引
    const struct _instr_info_t *info;
} instr_t;

//寻址模式
typedef enum _op_type_t
{
    OTYPE_NONE,
    OTYPE_IMM8,    // 8位立即数寻址
    OTYPE_Rn,
    OTYPE_DIRECT,    //直接寻址,在指令中给定了操作数的实际地址
    OTYPE_ACC,
    OTYPE_DPTR,
    OTYPE_IMM16,            // 16位立即数寻址
    OTYPE_INDIRECT_R0_1,    //寄存器间接寻址,但操作数放在R0或R1中
    OTYPE_C,                // carry flag
    OTYPE_BIT,              //位寻址
    OTYPE_INV_BIT,
    OTYPE_INDIRECT_ACC_PC,    //基址+变指间接寻址,以PC为基址寄存器,A作变指寄存器,相加形成16位的地址来访问程序存储区
    OTYPE_INDIRECT_ACC_DPTR,    //基址+变指间接寻址,以DPTR为基址寄存器,A作变指寄存器,相加形成16位的地址来访问程序存储区
    OTYPE_INDIRECT_DPTR,
    OTYPE_INDIRECT_SP,
    OTYPE_B,
} op_type_t;
//指令描述,包括有字节数,运行需要的机器周期数,寻址模式
typedef struct _instr_info_t
{
    //操作数的字节数
    uint8_t bytes;
    //操作执行需要的指令周期
    uint8_t cycles;
    //操作数0的寻指模式
    op_type_t op0_mode;
    //操作数1的寻指模式
    op_type_t op1_mode;
    //指令执行的功能
    void (*exec)(instr_t *instr);
    //指令操作码描述
    const char *disa_opcode;
    //指令操作数1描述
    const char *disa0;
    //指令操作数2描述
    const char *disa1;
} instr_info_t;

/**
 * @description: 执行每一条指令时,显示当前执行的指令
 * @param {instr_t} *instr
 * @return {*}
 */
void show_disa(instr_t *instr);
void do_nop(instr_t *instr);
void do_mov(instr_t *instr);
/**
 * @description: 访问程序存储器
 * @param {instr_t} *instr
 * @return {*}
 */
void do_movc(instr_t *instr);
/**
 * @description: 访问扩展存储器
 * @return {*}
 */
void do_movx(instr_t *instr);
/**
 * @description: push
 * @param {instr_t} *instr
 * @return {*}
 */
void do_push(instr_t *instr);
/**
 * @description: pop
 * @param {instr_t} *instr
 * @return {*}
 */
void do_pop(instr_t *instr);
/**
 * @description: ACC的高4位与低4位交换
 * @param {instr_t *} instr
 * @return {*}
 */
void do_swap(instr_t *instr);
/**
 * @description: xch 交换
 * 包括有xchd:exchange digit. xchd A,@R0  ; xchd A,@R1; 仅仅交换低端4个位
 * @param {instr_t} *instr
 * @return {*}
 */
void do_xch(instr_t *instr);
/**
 * @description: logical-and for byte variables
 * @param {instr_t} *instr
 * @return {*}
 */
void do_anl(instr_t *instr);
/**
 * @description: logical-OR for byte variables
 * orl c,bit include, fogical_OR for bit variables
 * @param {instr_t} *instr
 * @return {*}
 */
void do_orl(instr_t *instr);
/**
 * @description: logical exclusive-OR for byte variables
 * @param {instr_t} *instr
 * @return {*}
 */
void do_xrl(instr_t *instr);
/**
 * @description: clear bit. No other flags are affected
 * @param {instr_t} *instr
 * @return {*}
 */
void do_clr(instr_t *instr);
/**
 * @description: setb sets the indicated bit to one. the carry flag is cleared.
 * @param {instr_t} *instr
 * @return {*}
 */
void do_setb(instr_t *instr);
/**
 * @description: complement bit,补码位
 * @param {instr_t} *instr
 * @return {*}
 */
void do_cpl(instr_t *instr);
/**
 * @description: rotate acc left
 * @param {instr_t} *instr
 * @return {*}
 */
void do_rl(instr_t *instr);
/**
 * @description: rotate acc right
 * @param {instr_t} *instr
 * @return {*}
 */
void do_rr(instr_t *instr);

void do_add(instr_t *instr);
void do_subb(instr_t *instr);
void do_mul(instr_t *instr);
void do_div(instr_t *instr);
void do_inc(instr_t *instr);
void do_dec(instr_t *instr);
/**
 * @description: bcd码十进制的加法
 * @param {instr_t} *instr
 * @return {*}
 */
void do_da(instr_t *instr);

void do_acall(instr_t *instr);
void do_lcall(instr_t *instr);
void do_ajmp(instr_t *instr);
void do_ljmp(instr_t *instr);
/**
 * @description: 跳转范围sjmp:-128~127, addr8;ljmp:64k program addr16;ajmp: 2k block addr11
 * @param {instr_t} *instr
 * @return {*}
 */
void do_sjmp(instr_t *instr);
void do_jmp_a_dptr(instr_t *instr);

void do_jb(instr_t *instr);
void do_jc(instr_t *instr);
void do_jz(instr_t *instr);
void do_cjne(instr_t *instr);
void do_djnz(instr_t *instr);
void do_ret(instr_t *instr);
void do_reti(instr_t *instr);

#endif    // !INSTR_H
